
#include <iostream>
#include <unordered_map>

using namespace std;

class Name{
public:
	Name(string const& xing, string const& ming):m_xing(xing), m_ming(ming){}
	/*
	bool operator==(Name const& that) const {
		return m_xing == that.m_xing && m_ming == that.m_ming;
	}
	*/
private:
	string m_xing;
	string m_ming;
	friend ostream& operator<<(ostream& os, Name const& name);
	friend class NameHash;
};

ostream& operator<<(ostream& os, Name const& name){
	return os << name.m_xing << name.m_ming;
}

// Define a hash
class NameHash{
public:
	size_t operator()(Name const& name) const {
		hash<string> hs;
		return hs(name.m_xing) ^ (hs(name.m_ming)<<1);
	}
};

class NameEqual{
public:
	bool operator()(Name const& a, Name const& b) const {
		return a.m_xing == b.m_xing && a.m_ming == b.m_ming;
	}
};

int main(){
	unordered_map<Name, int, NameHash, NameEqual> m{
		{{"zhang", "san"}, 88}, {{"li", "si"}, 70},{{"wang", "wu"}, 85}
	};

	for(auto const& p : m)
		cout << p.first << ':' << p.second << endl;

	/*
	unordered_map<string, int> m{
		{"zhangsan", 88}, {"lisi", 70}, {"wangwu", 10}
	};
	cout << m["lisi"] << endl;
	hash<string> hs;
	for(auto const& p : m)
		cout << p.first << " (" << hs(p.first)  << ") : "<< p.second<< endl;
	*/

	return 0;
}
